<?php

namespace SunAdmin\Task;

use SunAdmin\Common\Utils;
use SunAdmin\Model\TimerTaskModel;
use Swoole\Timer;
use think\facade\Log;
use think\swoole\Manager;
use Throwable;

class TimerTaskManage
{
    protected $timerTasks = [];
    protected $timerTaskRunWorkerId = 0;
    protected $debugTimerId = null;
    protected Manager $swooleManager;

    public function __construct()
    {
        $this->swooleManager = app(Manager::class);
    }

    /**
     * 写入日志
     * @param string $message 日志消息
     * @param string $type 日志类型 info|error|warning|debug
     * @param array $context 上下文数据
     */
    private function log(string $message, string $type = 'info', array $context = [])
    {
        if(!env('APP_DEBUG') && $type !== 'error'){
            return;
        }
        $logMessage = "[TimerTaskManage] " . $message;
        if (!empty($context)) {
            $logMessage .= " | Context: " . json_encode($context, JSON_UNESCAPED_UNICODE);
        }
        trace($logMessage, $type);
    }

    public function start()
    {
        // 首先检查WorkerId，如果不匹配直接返回，不执行任何逻辑
        if ($this->swooleManager->getWorkerId() !== $this->timerTaskRunWorkerId) {
            return;
        }
        // 只在调试模式下启用
//        if (env('APP_DEBUG')) {
//            $this->debugTimerId = Timer::tick(1000, function () {
//                $this->swooleManager->runInSandbox(function () {
//                    foreach ($this->timerTasks as $timerTask) {
//                        dump("任务名:[{$timerTask['name']}],调度类型:[{$timerTask['type']}],状态:[{$timerTask['run_status']}]");
//                    }
//                });
//            });
//            $this->log('调试模式已启用，开始定时输出任务状态', 'debug');
//        }

        $this->log('开始启动定时任务管理器,workerId: ' . $this->swooleManager->getWorkerId(), 'info', [
            'worker_id' => $this->swooleManager->getWorkerId(),
            'target_worker_id' => $this->timerTaskRunWorkerId
        ]);

        // 清除旧的定时器
        $this->clearAllTimers();
        // 重新注册任务
        $this->register();
        // 启动任务
        $this->startAllTasks();

        $this->log('定时任务管理器启动完成', 'info', [
            'total_tasks' => count($this->timerTasks)
        ]);
        echo "✅ 定时任务管理器启动完成\n";
    }

    private function clearAllTimers()
    {
        $this->log('开始清除所有定时器', 'info');
        $clearedCount = 0;
        foreach ($this->timerTasks as $task) {
            if (isset($task['timer_id']) && $task['timer_id'] > 0) {
                Timer::clear($task['timer_id']);
                $clearedCount++;
            }
        }

        $this->log('定时器清除完成', 'info', ['cleared_count' => $clearedCount]);
    }

    private function startAllTasks()
    {
        $this->log('开始启动所有定时任务', 'info');
        $startedCount = 0;
        foreach ($this->timerTasks as $taskName => $task) {
            $taskName = $task['name'];
            switch ($task['type']) {
                case 'interval':
                    $this->startIntervalTask($taskName);
                    $startedCount++;
                    break;
                case 'daily':
                    $this->startDailyTask($taskName);
                    $startedCount++;
                    break;
                default:
                    $this->log('未知的任务类型', 'warning', [
                        'task_name' => $taskName,
                        'task_type' => $task['type']
                    ]);
                    break;
            }
        }

        $this->log('所有定时任务启动完成,总数:' . $startedCount, 'info', ['started_count' => $startedCount]);
    }

    private function startIntervalTask($taskName)
    {

        $task = $this->timerTasks[$taskName];

        if (!isset($task['schedule_config']['interval']) || $task['schedule_config']['interval'] <= 0) {
            $this->log('间隔任务配置无效', 'error', [
                'task_name' => $task['name'],
                'config' => $task['schedule_config'] ?? null
            ]);
            Log::warning("间隔任务配置无效: " . $task['name']);
            return;
        }

        $interval = $task['schedule_config']['interval'];
        $this->timerTasks[$taskName]['timer_id'] = Timer::tick($interval * 1000, function () use ($taskName) {
            $this->execTask($taskName);
        });

        $this->log('间隔任务启动成功', 'info', [
            'task_name' => $taskName,
            'interval' => $interval,
            'timer_id' => $this->timerTasks[$taskName]['timer_id']
        ]);
    }

    private function startDailyTask($taskName)
    {
        if (!isset($this->timerTasks[$taskName]['schedule_config']['time'])) {
            $this->log('每日任务时间配置无效', 'error', [
                'task_name' => $taskName,
                'config' => $this->timerTasks[$taskName]['schedule_config'] ?? null
            ]);
            Log::warning("每日任务时间配置无效: " . $taskName);
            return;
        }

        $executeTime = $this->timerTasks[$taskName]['schedule_config']['time'];
        $this->timerTasks[$taskName]['timer_id'] = Timer::tick(60000, function () use ($taskName) { // 每分钟检查
            $currentTime = date('H:i');
            if ($currentTime === $this->timerTasks[$taskName]['schedule_config']['time']) {
                $this->execTask($taskName);
            }
        });

        $this->log('每日任务启动成功', 'info', [
            'task_name' => $taskName,
            'execute_time' => $executeTime,
            'timer_id' => $this->timerTasks[$taskName]['timer_id']
        ]);
    }

    private function execTask($taskName)
    {
        $this->swooleManager->runInSandbox(function () use ($taskName) {
            if ($this->timerTasks[$taskName]['run_status'] === 'running') {
                $this->log('任务正在运行，跳过执行', 'warning', ['task_name' => $taskName]);
                return;
            }
            try {
                $this->timerTasks[$taskName]['run_status'] = 'running';
                $this->timerTasks[$taskName]['last_run_time'] = Utils::timeToStr();
                // 准备执行具体任务
                $className = $this->timerTasks[$taskName]['class_name'];
                $methodName = $this->timerTasks[$taskName]['method_name'];
                // 检查类和方法是否存在
                if (!class_exists($className)) {
                    throw new \Exception("任务类不存在: " . $className);
                }
                $taskInstance = new $className();
                if (!method_exists($taskInstance, $methodName)) {
                    throw new \Exception("任务方法不存在: " . $className . "::" . $methodName);
                }
                //执行任务
                $taskInstance->$methodName($this->timerTasks[$taskName]['id']);
                //执行完毕
                $this->timerTasks[$taskName]['run_status'] = 'success';
            } catch (Throwable $e) {
                $this->timerTasks[$taskName]['failed_executions'] += 1;
                $this->timerTasks[$taskName]['run_status'] = 'error';
                $this->log("定时任务管理器执行任务[{$taskName}]失败,".$e->getMessage(), 'error');
            }
        });
    }

    private function register()
    {
        $this->log('开始注册定时任务', 'info');
        $tasks = TimerTaskModel::where(['enabled' => 1])->select();
        if ($tasks->isEmpty()) {
            $this->timerTasks = [];
            $this->log('没有找到启用的定时任务', 'warning');
            return;
        }

        $this->timerTasks = [];
        $registeredCount = 0;
        foreach ($tasks as $task) {
            $this->timerTasks[$task->name] = [
                ...$task->toArray(),
                'run_status' => 'stop',
                'timer_id' => null
            ];
            $registeredCount++;
        }
        $this->log('定时任务注册完成', 'info', [
            'registered_count' => $registeredCount,
            'task_names' => array_keys($this->timerTasks)
        ]);
    }
}